/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/08/10
*/
#ifndef __EDUI_EVENT_H__
#define __EDUI_EVENT_H__

#include "defines.h"
#include <iostream>
using namespace std;

EDUI_NAMESPACE_BEGIN

#define EDUI_EVENT_MAX_NUM 1

class EDUI_API Object{};

class EDUI_API IEvent
{
public:
    virtual void disconnect() = 0;
    virtual void disconnect(Object* obj) = 0;
};

template<int maxnum = EDUI_EVENT_MAX_NUM>
class EDUI_API Event : public IEvent
{
public:
    Event()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
public:
    template<typename funcType>
    bool connect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((0 == m_obj[i]) && (0 == m_func[i])){
                m_obj[i] = obj;
                m_func[i] = static_cast<Func>(func);
                return true;
            }
        }

        return false;
    }

    template<typename funcType>
    void disconnect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i]) && (func == m_func[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
                return;
            }
        }
    }

    void disconnect(Object* obj)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
            }
        }
    }
    
    void disconnect()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
    
    void emit()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((m_obj[i]) && (m_func[i])){
                ((m_obj[i])->*(m_func[i]))();
            }
        }
    }
private:
    typedef void (Object::*Func)();
    Object* m_obj[maxnum];
    Func m_func[maxnum];
};

template<typename ArgType1, int maxnum = EDUI_EVENT_MAX_NUM>
class EDUI_API Event1 : public IEvent
{
public:
    Event1()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
public:
    template<typename funcType>
    bool connect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((0 == m_obj[i]) && (0 == m_func[i])){
                m_obj[i] = obj;
                m_func[i] = static_cast<Func>(func);
                return true;
            }
        }

        return false;
    }

    template<typename funcType>
    void disconnect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i]) && (func == m_func[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
                return;
            }
        }
    }

    void disconnect(Object* obj)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
            }
        }
    }
    
    void disconnect()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
    
    void emit(ArgType1 arg1)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((m_obj[i]) && (m_func[i])){
                ((m_obj[i])->*(m_func[i]))(arg1);
            }
        }
    }
private:
    typedef void (Object::*Func)(ArgType1 arg1);
    Object* m_obj[maxnum];
    Func m_func[maxnum];
};

template<typename ArgType1, typename ArgType2, int maxnum = EDUI_EVENT_MAX_NUM>
class EDUI_API Event2 : public IEvent
{
public:
    Event2()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
public:
    template<typename funcType>
    bool connect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((0 == m_obj[i]) && (0 == m_func[i])){
                m_obj[i] = obj;
                m_func[i] = static_cast<Func>(func);
                return true;
            }
        }

        return false;
    }

    template<typename funcType>
    void disconnect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i]) && (func == m_func[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
                return;
            }
        }
    }

    void disconnect(Object* obj)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
            }
        }
    }
    
    void disconnect()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
    
    void emit(ArgType1 arg1, ArgType2 arg2)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((m_obj[i]) && (m_func[i])){
                ((m_obj[i])->*(m_func[i]))(arg1, arg2);
            }
        }
    }
private:
    typedef void (Object::*Func)(ArgType1 arg1, ArgType2 arg2);
    Object* m_obj[maxnum];
    Func m_func[maxnum];
};

template<typename ArgType1, typename ArgType2, typename ArgType3, int maxnum = EDUI_EVENT_MAX_NUM>
class EDUI_API Event3 : public IEvent
{
public:
    Event3()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
public:
    template<typename funcType>
    bool connect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((0 == m_obj[i]) && (0 == m_func[i])){
                m_obj[i] = obj;
                m_func[i] = static_cast<Func>(func);
                return true;
            }
        }

        return false;
    }

    template<typename funcType>
    void disconnect(Object* obj, funcType func)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i]) && (func == m_func[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
                return;
            }
        }
    }

    void disconnect(Object* obj)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((obj == m_obj[i])){
                m_obj[i] = 0;
                m_func[i] = 0;
            }
        }
    }
    
    void disconnect()
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            m_obj[i] = 0;
            m_func[i] = 0;
        }
    }
    
    void emit(ArgType1 arg1, ArgType2 arg2, ArgType3 arg3)
    {
        for (Uint8 i = 0; i < maxnum; ++i){
            if ((m_obj[i]) && (m_func[i])){
                ((m_obj[i])->*(m_func[i]))(arg1, arg2, arg3);
            }
        }
    }
private:
    typedef void (Object::*Func)(ArgType1 arg1, ArgType2 arg2, ArgType3 arg3);
    Object* m_obj[maxnum];
    Func m_func[maxnum];
};

EDUI_NAMESPACE_END

#endif
